#include "clientFunc.h"

// 发送成功信息
int successSend(int sockfd) {
    send(sockfd, "o", 1, MSG_NOSIGNAL);
    return 0;
}

// 发送错误信息, 如果填入NULL, 发送一个'e'报错信号
// 如果填入字符串, 将其作为报错信息发送给客户端
int errorSend(int sockfd, const char* errorMsg) {
    if(errorMsg == NULL) {
        send(sockfd, "e", 1, MSG_NOSIGNAL);
    }
    else {
        train_t train;
        strSend(sockfd, &train, errorMsg);
    }
    return 0;
}

// 接收确认信息, 信息正确时返回1, 错误时返回0
int recvMsg(int sockfd, train_t* ptrain) {
    char msgFlag[1] = {0};
    recvn(sockfd, msgFlag, sizeof(msgFlag));
    if(msgFlag[0] == 'e') {
        memset(ptrain, 0, sizeof(train_t));
        recvn(sockfd, &ptrain->length, sizeof(int));
        recvn(sockfd, ptrain->data, ptrain->length);
        printf("%s\n", ptrain->data);
        return 0;
    }
    return 1;
}

// 用小火车发送字符串
int strSend(int sockfd, train_t* ptrain, const char* str) {
        memset(ptrain, 0, sizeof(train_t));
        ptrain->length = strlen(str) + 1;
        memcpy(ptrain->data, str, ptrain->length);
        send(sockfd, ptrain, ptrain->length + sizeof(int), MSG_NOSIGNAL);
        return 0;
}

// 传入cmd_t，解析并执行相应的指令函数,传入cwd_t为指令函数传参
int cmdClientHandler(int sockfd, const cmd_t *pcmd) {
    switch(pcmd->cmdToken[0]) {
    case'c': cdProc(sockfd); break; 
    case'l': {
                 switch(pcmd->cmdToken[1]) {
                 case's': lsProc(sockfd); break;
                 case'o': {
                              switch(pcmd->cmdToken[3]) {
                              case'i': userLoginProc(sockfd, pcmd);break;
                              case'o': userLogoutProc();break;
                              }
                          } break;
                 }
             } break;
    case'p': {
                 switch(pcmd->cmdToken[1]) {
                 case'u': clientPuts(sockfd, pcmd); break;
                 case'w': pwdProc(sockfd); break;
                 }
             } break;
    case'u':{
                switch(pcmd->cmdToken[4]){
                case'a':userAddProc(sockfd);break;
                case'd':userDelProc(sockfd);break;
                }
            } break;
    case'g': clientGets(sockfd, pcmd); break;
    case'm': mkdirProc(sockfd); break;
    case'r': rmProc(sockfd); break;
    }
    return 0;
}

// 判断路径是否和传入类型匹配
// 传入S_IFREG(普通文件)或S_IFDIR(目录)判断类型
// 返回1类型相符, 返回0类型不符, 返回-1路径无法访问
int pathJudge(const char* realPath, mode_t mode) {
    if(access(realPath, F_OK) == 0) {
        struct stat fileInfo;
        ssize_t sret = stat(realPath, &fileInfo);
        ERROR_CHECK(sret, -1, "stat");
        if((fileInfo.st_mode & S_IFMT) == mode) {
            return 1;
        }
        else {
            return 0;
        }
    }
    return -1;
}

// pwd指令(遍历栈),pwdstr用于存储遍历后的结果
int pwdProc(int sockfd) {
    train_t train;
    memset(&train, 0, sizeof(train_t));
    recvn(sockfd, &train.length, sizeof(int));
    recvn(sockfd, train.data, train.length);
    printf("%s\n", train.data);
    return 0;
}

// 将整个目录流中的内容发送给客户端
int readDir(int sockfd, train_t* train) {
    while(1) {
        memset(train, 0, sizeof(train_t));
        recvn(sockfd, &train->length, sizeof(int));
        if(train->length == 0) {
            break;
        }
        recvn(sockfd, train->data, train->length);
        printf("%s\t", train->data);
    }
    return 0;
}

// ls指令,cwd_t获取cwd,cmd_t获取指令及参数
int lsProc(int sockfd) {
    train_t train;
    if(recvMsg(sockfd, &train)) {
        readDir(sockfd, &train);
    }
    printf("\n");
    return 0;
}

// cd指令,修改cwd栈,cmd_t获取指令及参数
int cdProc(int sockfd) {
    train_t train;
    recvMsg(sockfd, &train);
    return 0;
}    
